package tests;

import static org.junit.Assert.*;

import java.io.FileInputStream;
import java.net.Socket;
import java.util.Properties;

import org.junit.Test;

import sql.CacheHandler;

import cs236369.proxy.ProxyServer;


public class Hw3Tests {

	
	private ProxyServer proxy;
	private int proxyport;
	private Properties p;
	private Thread proxyThread;
	
	public Hw3Tests() throws Exception {
		
		p = new Properties();
		
		p.load(new FileInputStream("config"));
		proxy = new ProxyServer(p);
		proxy.createCacheTable();
		proxyport = Integer.parseInt(p.getProperty("proxy.port"));
		proxyThread = new Thread(new Runnable() {
			
			@Override
			public void run() {
				proxy.start();
			}
		});
		proxyThread.start();
		
		// wait for proxy to init
		Thread.sleep(3000);
	}
	
	@Test
	public void test1() throws Exception {
		
		proxy.cacheClear();
		String res = "HTTP/1.1 200 OK\r\n" +
			"Content-Length: 10\r\n" +
			"\r\n" +
			"1234567890";
			
		TestServer ts = new TestServer(res, 54321);
		Socket s = null;
		Thread t = new Thread(ts);
		t.start();
		try {
			s = new Socket("localhost", proxyport);
			String req = "GET http://localhost:54321/x HTTP/1.1\r\n" +
					"Host: localhost:54321\r\n" +
					"Cache-Control: no-cache\r\n" +
					"\r\n";
			s.getOutputStream().write(req.getBytes());
			s.getOutputStream().flush();	
		} finally {
			try { s.close(); } catch (Exception e) {}
			t.join();
		}
		System.out.println(ts.getRequest());
		assertFalse(ts.getRequest().isEmpty());
	}
	
	
	/**************************************************************************
	 * Testing the failure of the cache conditions:
	 * 	1. 	the response isn't 200
	 * 	2.	no-store or no-cache
	 * 	3.	their isn't Last-Modified
	 **************************************************************************/
	
	/**
	 * the response isn't 200 so it shouldn't be in the cache
	 */
	//@Test
	public void test2() throws Exception {
		
		proxy.cacheClear();
		String res = "HTTP/1.1 404 OK\r\n" +
		"Content-Length: 10\r\n" +
		"\r\n" +
		"1234567890";
		
		TestServer ts = new TestServer(res, 54322);
		Socket s = null;
		Thread t = new Thread(ts);
		t.start();
		try {
			s = new Socket("localhost", proxyport);
			String req = "GET http://localhost:54322/x HTTP/1.1\r\n" +
					"Host: localhost:54322\r\n" +
					"Cache-Control: no-cache\r\n" +
					"\r\n";
			s.getOutputStream().write(req.getBytes());
			s.getOutputStream().flush();	
		} finally {
			try { s.close(); } catch (Exception e) {}
			t.join();
		}
		System.out.println(ts.getRequest());
		assertFalse(ts.getRequest().isEmpty());
		CacheHandler.printCacheContent(p);
	}
	
	/**
	 * the Cache-Control is no-cache
	 * @throws Exception
	 */
	//@Test
	public void test3() throws Exception {
		
		proxy.cacheClear();
		String res = "HTTP/1.1 200 OK\r\n" +
		"Content-Length: 10\r\n" +
		"Cache-Control: no-cache\r\n" +
		"\r\n" +
		"1234567890";
		
		TestServer ts = new TestServer(res, 54323);
		Socket s = null;
		Thread t = new Thread(ts);
		t.start();
		try {
			s = new Socket("localhost", proxyport);
			String req = "GET http://localhost:54323/x HTTP/1.1\r\n" +
					"Host: localhost:54323\r\n" +
					"Cache-Control: no-cache\r\n" +
					"\r\n";
			s.getOutputStream().write(req.getBytes());
			s.getOutputStream().flush();	
		} finally {
			try { s.close(); } catch (Exception e) {}
			t.join();
		}
		System.out.println(ts.getRequest());
		assertFalse(ts.getRequest().isEmpty());
		CacheHandler.printCacheContent(p);
	}
	
	/**
	 * the Cache-Control is no-store
	 * @throws Exception
	 */
	//@Test
	public void test4() throws Exception {
		
		proxy.cacheClear();
		String res = "HTTP/1.1 200 OK\r\n" +
		"Content-Length: 10\r\n" +
		"Cache-Control: no-store\r\n" +
		"\r\n" +
		"1234567890";
		
		TestServer ts = new TestServer(res, 54324);
		Socket s = null;
		Thread t = new Thread(ts);
		t.start();
		try {
			s = new Socket("localhost", proxyport);
			String req = "GET http://localhost:54324/x HTTP/1.1\r\n" +
					"Host: localhost:54324\r\n" +
					"Cache-Control: no-cache\r\n" +
					"\r\n";
			s.getOutputStream().write(req.getBytes());
			s.getOutputStream().flush();	
		} finally {
			try { s.close(); } catch (Exception e) {}
			t.join();
		}
		System.out.println(ts.getRequest());
		assertFalse(ts.getRequest().isEmpty());
		CacheHandler.printCacheContent(p);
	}
	
	/**
	 * their isn't Last-Modified
	 * @throws Exception
	 */
	//@Test
	public void test5() throws Exception {
		
		proxy.cacheClear();
		String res = "HTTP/1.1 200 OK\r\n" +
		"Content-Length: 10\r\n" +
		"\r\n" +
		"1234567890";
		
		TestServer ts = new TestServer(res, 54325);
		Socket s = null;
		Thread t = new Thread(ts);
		t.start();
		try {
			s = new Socket("localhost", proxyport);
			String req = "GET http://localhost:54325/x HTTP/1.1\r\n" +
					"Host: localhost:54325\r\n" +
					"Cache-Control: no-cache\r\n" +
					"\r\n";
			s.getOutputStream().write(req.getBytes());
			s.getOutputStream().flush();	
		} finally {
			try { s.close(); } catch (Exception e) {}
			t.join();
		}
		System.out.println(ts.getRequest());
		assertFalse(ts.getRequest().isEmpty());
		CacheHandler.printCacheContent(p);
	}
	
	/**
	 * first time caching 
	 * @throws Exception
	 */
	//@Test
	public void test6() throws Exception {
		
		proxy.cacheClear();
		String res = "HTTP/1.1 200 OK\r\n" +
		"Content-Length: 10\r\n" +
		"Last-Modified: 0\r\n" +
		"\r\n" +
		"1234567890";
		
		TestServer ts = new TestServer(res, 54326);
		Socket s = null;
		Thread t = new Thread(ts);
		t.start();
		try {
			s = new Socket("localhost", proxyport);
			String req = "GET http://localhost:54326/x HTTP/1.1\r\n" +
					"Host: localhost:54326\r\n" +
					"\r\n";
			s.getOutputStream().write(req.getBytes());
			s.getOutputStream().flush();	
		} finally {
			try { s.close(); } catch (Exception e) {}
			t.join();
		}
		System.out.println(ts.getRequest());
		assertFalse(ts.getRequest().isEmpty());
		CacheHandler.printCacheContent(p);
		
		// wait for proxy 
		Thread.sleep(3000);
	}
	
	/**
	 * in the cache and we don't want to update
	 * @throws Exception
	 */
	//@Test
	public void test7() throws Exception {
		
		proxy.cacheClear();
		String res1 = "HTTP/1.1 200 OK\r\n" +
		"Content-Length: 10\r\n" +
		"Last-Modified: 0\r\n" +
		"\r\n" +
		"1234567890";
		
		String res2 = "HTTP/1.1 304 OK\r\n" +
		"\r\n";
		
		TestServer ts = new TestServer(res1, 54327);
		Socket s = null;
		Thread t = new Thread(ts);
		Thread t2 = new Thread(ts);
		t.start();
		try {
			s = new Socket("localhost", proxyport);
			String req = "GET http://localhost:54327/x HTTP/1.1\r\n" +
					"Host: localhost:54327\r\n" +
					"\r\n";
			s.getOutputStream().write(req.getBytes());
			s.getOutputStream().flush();
			

			ts.setResponse(res2);
			Thread.sleep(3000);
			t2.start();
			s.getOutputStream().write(req.getBytes());
			s.getOutputStream().flush();
			int c = s.getInputStream().read();
			while (c != -1){
				System.out.print((char)c);
				c = s.getInputStream().read();
			}
			System.out.println();
			
		} finally {
			try { s.close(); } catch (Exception e) {}
			t.join();
			t2.join();
		}
		System.out.println(ts.getRequest());
		assertFalse(ts.getRequest().isEmpty());
		CacheHandler.printCacheContent(p);
		
		// wait for proxy 
		Thread.sleep(3000);
	}
	
	//@Test
	public void test8() throws Exception {
		
		//proxy.cacheClear();
		String res2 = "HTTP/1.1 200 OK\r\n" +
		"Content-Length: 10\r\n" +
		"Last-Modified: 0\r\n" +
		"\r\n" +
		"1234567890";
		
		String res1 = "HTTP/1.1 200 OK\r\n" +
		"Content-Length: 10\r\n" +
		"Last-Modified: 0\r\n" +
		"\r\n" +
		"0987654321";
		
		TestServer ts = new TestServer(res1, 54327);
		TestServer ts2 = new TestServer(res2, 54328);
		Socket s = null;
		Thread t = new Thread(ts);
		Thread t2 = new Thread(ts2);
		t.start();
		ts2.setResponse(res2);
		t2 = new Thread(ts2);
		try {
			s = new Socket("localhost", proxyport);
			String req = "GET http://localhost:54327/x HTTP/1.1\r\n" +
					"Host: localhost:54327\r\n" +
					"Cache-Control: no-cache\r\n" +
					"Transfer-Encoding: yomama\r\n" +
					"Accept-Encoding: yomama\r\n" +
					"\r\n";
			String req2 = "GET http://localhost:54327/x HTTP/1.1\r\n" +
			"Host: localhost:54327\r\n" +
			"\r\n";
			s.getOutputStream().write(req.getBytes());
			s.getOutputStream().flush();
			int c;
			System.out.println("reading response from server first time");
			c = s.getInputStream().read();
			while (c != -1){
				System.out.print((char)c);
				c = s.getInputStream().read();
			}	
			System.out.println("\nend read");

			s.close();
//			System.out.println("socket closed: " + s.isClosed());
//			Thread.sleep(3000);
//			t2.start();
//			s = new Socket("localhost", proxyport);
//			s.getOutputStream().write(req2.getBytes());
//			s.getOutputStream().flush();
//			System.out.println("reading response from server second time");
//			c = s.getInputStream().read();
//			while (c != -1){
//				System.out.print((char)c);
//				c = s.getInputStream().read();
//			}
//			System.out.println("\nend read");
//			System.out.println();
			
		} finally {
			try { s.close(); } catch (Exception e) {}
			t.join();
			t2.join();
		}
		System.out.println(ts.getRequest());
		System.out.println(ts2.getRequest());
		assertFalse(ts.getRequest().isEmpty());
		CacheHandler.printCacheContent(p);
		
		// wait for proxy 
		Thread.sleep(3000);
	}
}
